///////////////////////////////////////////////////////////////////////////////
//
// Copyright
//
///////////////////////////////////////////////////////////////////////////////

package ru.goodcore.css.datastructure
{

import ru.goodcore.datastructure.IIterableAggregate;
import ru.goodcore.datastructure.IIterator;

/**
 * Implements double-linked list structute
 * 
 * 
 * @author					Dimarik
 * @version					1.0
 * @playerversion			Flash 9
 * @langversion				3.0
 * 
 * @see						http://en.wikipedia.org/wiki/Linked_list
 *
 * @keyword					linkedlist, linkedlistnode, datastructure
 */
public class LinkedList extends LinkedListNode implements IIterableAggregate
{

	//-------------------------------------------------------------------------
	//
	//  Constructor
	//
	//-------------------------------------------------------------------------

	/**
	 * Constructor
	 */
	public function LinkedList() {
		super();
	}

	//-------------------------------------------------------------------------
	//
	//  Private variables
	//
	//-------------------------------------------------------------------------

	/**
	 * @private 
	 */
	internal var $head:			LinkedListNode;

	/**
	 * @private 
	 */
	private var _tail:			LinkedListNode;

	/**
	 * @private 
	 */
	private var _length:	uint = 0;

	public function get length():uint {
		return this._length;
	}

	//-------------------------------------------------------------------------
	//
	//  Interface Implementation: IIteratableAggregate
	//
	//-------------------------------------------------------------------------

	public function createIterator(node:* = null):IIterator {
		return new Iterator(node || this.$head);
	}

	public function isEmpty():Boolean {
		return this._length == 0;
	}

	/**
	 * Adds one or more elements to the tail of the list and returns the new length of the list.
	 *  
	 * @param 	args
	 * @return	An integer representing the length of the new list
	 * 
	 */
	public function append(...args /* of LinkedListNode */):uint {
		var node:	LinkedListNode;
		var tail:	LinkedListNode = this._tail;

		var i:		uint;
		var len:	uint = (args as Array).length;

		if ( !tail ) {
			node = args[0] as LinkedListNode;
			tail = this.$head = node;
			i = 1;
		}

		for (; i < len; i++) {
			node = args[i] as LinkedListNode;
			tail.$next = node;
			node.$prev = tail;
			tail = node;
		}

		this._length += len;

		this._tail = tail;

		return this._length;
	}

}
}

//=============================================================================
//
//   Inner definitions
//
//=============================================================================

import ru.goodcore.css.datastructure.LinkedListNode;
import ru.goodcore.datastructure.IIterator;

/**
 * @private
 */
internal class Iterator implements IIterator {

	public function Iterator(node:LinkedListNode) {
		super();
		this._current = node;
	}

	/**
	 * @private
	 */	
	private var _current:	LinkedListNode;

	//-------------------------------------------------------------------------
	//
	//   Interface implementation: IIterator
	//
	//-------------------------------------------------------------------------

	//---------------------------------
	//  hasNext
	//---------------------------------

	public function get hasNext():Boolean {
		return this._current != null;
	}

	//---------------------------------
	//  hasPrev
	//---------------------------------

	public function get hasPrev():Boolean {
		return this._current.prev != null;
	}

	//---------------------------------
	//  next
	//---------------------------------

	public function get next():* {
		var node:	LinkedListNode = this._current;
		this._current = this._current.next;
		return node;
	}

	//---------------------------------
	//  prev
	//---------------------------------

	public function get prev():* {
		var node:	LinkedListNode = this._current;
		this._current = this._current.prev;
		return node;
	}

	//---------------------------------
	//  current
	//---------------------------------

	public function get current():* {
		return this._current;
	}

}